package com.avocado.bt.impl.composite;

import com.avocado.bt.BTState;
import com.avocado.bt.IBTContext;
import com.avocado.bt.IBTNode;
import com.avocado.bt.abs.composite.CompositeNode;

import java.util.Collection;

/**
 * 根据配置策略执行一个或者多个节点
 *
 * @Author: zsh
 * @Date: 2023/10/16 17:14
 */
public class ParallelNode extends CompositeNode {

    private ParallelPolicyEnum successPolicy;
    private ParallelPolicyEnum failPolicy;

    public ParallelNode(String param) {
        super(param);
        String[] policys = param.split("_");
        for (ParallelPolicyEnum value : ParallelPolicyEnum.values()) {
            if (value.name().equalsIgnoreCase(policys[0])) {
                successPolicy = value;
            }
            if (value.name().equalsIgnoreCase(policys[1])) {
                failPolicy = value;
            }
        }
    }

    @Override
    public BTState doUpdate(IBTContext context) {
        int successCount = 0, failureCount = 0;
        Collection<IBTNode> childNodes = getChildNodes();
        int childrenSize = childNodes.size();
        for (IBTNode childNode : childNodes) {
            if (!(BTState.Completed.equals(childNode.getState()) || BTState.Failure.equals(childNode.getState()))) {
                BTState tick = childNode.tick();
                if (BTState.Completed.equals(tick)) {
                    successCount++;
                } else if (BTState.Failure.equals(childNode.getState())) {
                    failureCount++;
                }
            }
            // 检查当前子节点的状态是否满足本节点的策略
            if (successPolicy.equals(ParallelPolicyEnum.RequireOne) && successCount == 1) {
                return BTState.Completed;
            }
            if (failPolicy.equals(ParallelPolicyEnum.RequireOne) && failureCount >= 1) {
                return BTState.Failure;
            }
        }
        // 检查所有子节点的状态是否满足本节点的策略
        if (failPolicy.equals(ParallelPolicyEnum.RequireAll) && failureCount == childrenSize) {
            return BTState.Failure;
        }
        if (successPolicy.equals(ParallelPolicyEnum.RequireAll) && successCount == childrenSize) {
            return BTState.Completed;
        }
        return BTState.Running;
    }


    enum ParallelPolicyEnum {
        RequireOne,
        RequireAll,
        ;
    }

}
